home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Development Platforms / Apple II / Essentials / Dynamo 4.2 for GSBug 1.5b10 / dynamo.includes / rt.macros < prev    next >
Encoding:
Text File  |  1990-09-21  |  40.0 KB  |  1,838 lines  |  [TEXT/MPS ]

  1. *******************************************************
  2. *                        *
  3. * DYNAMO                        *
  4. *                        *
  5. * Apple II 8-bit runtime macros.            *
  6. * Copyright (C) 1990 Apple Computer.        *
  7. * Version 4.1                    *
  8. *                        *
  9. * Written by Eric Soldan, Apple II DTS        *
  10. *                        *
  11. *******************************************************
  12.  
  13. * These macros are interfaces for the runtime routines associated with them.
  14. * The runtime routines handle up to 128 integer variables, and up to 256
  15. * strings.  The integer functions are simple add,sub,mul,div, and others.
  16. * These others include mass-initialization, min, max, print decimal, etc.
  17. * The string functions are most of what is available in AppleSoft, in
  18. * various forms.  There is also support for multi-dimension arrays.
  19.  
  20. * The principle of the runtime routines is that the xreg holds a destination
  21. * variable number (for ints: 0-254, for strings: 0-255).  All runtimes preserve
  22. * the xreg, therefore, you can do multiple operations to a single variable
  23. * without having to reload the xreg.  The values that are used on the xreg
  24. * variable (the source data), is one of 3 forms for integers:
  25. *    1. 1-byte value
  26. *    2. 2-byte value
  27. *    3. 2-byte integer variable.
  28. * 1-byte values are placed in the acc.  2-byte values are placed in the acc,y
  29. * (acc=lo, y=hi).  2-byte integer variables have the variable number placed in
  30. * the yreg.  (The yreg is not preserved by the runtime routines.)
  31. * Once the source data is loaded (in acc, acc-y, or y), the proper call to the
  32. * runtime routines is made.  The 'proper' routine is based on the type of data
  33. * the source is.  (If the source is a variable, and we are adding, the macro
  34. * will call the addvar routine.)
  35.  
  36. * Strings are also referenced by number.  There are 3 tables for strings:
  37. *    1. String length table.
  38. *    2. Max string length table.
  39. *    3. Pointer table.
  40. * So, each string takes up four bytes, plus however long the max string length
  41. * is.  Having the pointer allows the program to point into memory that was
  42. * never loaded or initialized.  This can save time loading the application from
  43. * disk.  The string routines will never overwrite the buffer space alloced for
  44. * them.  The string will be truncated.  So, you can append strings without
  45. * worry about clobbering memory.
  46.  
  47.  
  48. *****************************************************************
  49. *****************************************************************
  50. *****************************************************************
  51.  
  52. * These macros are called by other macros in this file.
  53.  
  54. ***************************************
  55.  
  56.     MACRO
  57.     acorm    &op
  58.     lclc    &str
  59. &str    setc    &op
  60.     if    &substr(&str,1,1)='#' goto .imm
  61.     if    &substr(&str,1,1)<>'*' then
  62.     aerror    'non-variable parameter must start with a # or *'
  63.     mexit
  64.     endif
  65. &str    setc    &substr(&str,2,999)
  66.     lcla    &deref
  67. &deref    seta    0
  68. .a    if    &substr(&str,1,1)<>'*' goto .b
  69. &str    setc    &substr(&str,2,999)
  70. &deref    seta    &deref+1
  71.     goto    .a
  72. .b    if    &substr(&str,1,1)='<' then
  73. &str    setc    &substr(&str,2,999)
  74.     endif
  75.     if    &deref>0 then
  76.     lda    &str+1
  77.     sta    aderefz+2
  78.     endif
  79.     lda    &str
  80. .d    if    &deref>0 then
  81.     jsr    aderef
  82. &deref    seta    &deref-1
  83.     goto    .d
  84.     endif
  85.     mexit
  86. .imm
  87. &str    setc    &substr(&str,2,999)
  88.     if    &substr(&str,1,1)='<' then
  89. &str    setc    &substr(&str,2,999)
  90.     endif
  91.     lda    #<&str
  92.     MEND
  93.  
  94. ***************************************
  95.  
  96.     MACRO
  97.     xcorm    &op
  98.     lclc    &str
  99. &str    setc    &op
  100.     if    &substr(&str,1,1)='#' goto .imm
  101.     if    &substr(&str,1,1)<>'*' then
  102.     aerror    'non-variable parameter must start with a # or *'
  103.     mexit
  104.     endif
  105. &str    setc    &substr(&str,2,999)
  106.     lcla    &deref
  107. &deref    seta    0
  108. .a    if    &substr(&str,1,1)<>'*' goto .b
  109. &str    setc    &substr(&str,2,999)
  110. &deref    seta    &deref+1
  111.     goto    .a
  112. .b    if    &substr(&str,1,1)='<' then
  113. &str    setc    &substr(&str,2,999)
  114.     endif
  115.     if    &deref>0 then
  116.     ldx    &str+1
  117.     stx    xderefz+2
  118.     endif
  119.     ldx    &str
  120. .d    if    &deref>0 then
  121.     jsr    xderef
  122. &deref    seta    &deref-1
  123.     goto    .d
  124.     endif
  125.     mexit
  126. .imm
  127. &str    setc    &substr(&str,2,999)
  128.     if    &substr(&str,1,1)='<' then
  129. &str    setc    &substr(&str,2,999)
  130.     endif
  131.     ldx    #<&str
  132.     MEND
  133.  
  134. ***************************************
  135.  
  136.     MACRO
  137.     ycorm    &op
  138.     lclc    &str
  139. &str    setc    &op
  140.     if    &substr(&str,1,1)='#' goto .imm
  141.     if    &substr(&str,1,1)<>'*' then
  142.     aerror    'non-variable parameter must start with a # or *'
  143.     mexit
  144.     endif
  145. &str    setc    &substr(&str,2,999)
  146.     lcla    &deref
  147. &deref    seta    0
  148. .a    if    &substr(&str,1,1)<>'*' goto .b
  149. &str    setc    &substr(&str,2,999)
  150. &deref    seta    &deref+1
  151.     goto    .a
  152. .b    if    &substr(&str,1,1)='<' then
  153. &str    setc    &substr(&str,2,999)
  154.     endif
  155.     if    &deref>0 then
  156.     ldy    &str+1
  157.     sty    yderefz+2
  158.     endif
  159.     ldy    &str
  160. .d    if    &deref>0 then
  161.     jsr    yderef
  162. &deref    seta    &deref-1
  163.     goto    .d
  164.     endif
  165.     mexit
  166. .imm
  167. &str    setc    &substr(&str,2,999)
  168.     if    &substr(&str,1,1)='<' then
  169. &str    setc    &substr(&str,2,999)
  170.     endif
  171.     ldy    #<&str
  172.     MEND
  173.  
  174. ***************************************
  175.  
  176.     MACRO
  177.     axcorm    &op
  178. axisbyte    set    0
  179.     lclc    &str
  180. &str    setc    &op
  181.     if    &substr(&str,1,1)='#' goto .imm
  182.     if    &substr(&str,1,1)<>'*' then
  183.     aerror    'non-variable parameter must start with a # or *'
  184.     mexit
  185.     endif
  186. &str    setc    &substr(&str,2,999)
  187.     lcla    &deref
  188. &deref    seta    0
  189. .a    if    &substr(&str,1,1)<>'*' goto .b
  190. &str    setc    &substr(&str,2,999)
  191. &deref    seta    &deref+1
  192.     goto    .a
  193. .b    if    &substr(&str,1,1)='<' then
  194. axisbyte    set    1
  195. &str    setc    &substr(&str,2,999)
  196.     endif
  197.     lda    &str
  198.     if    &deref>0 goto .c
  199.     if    axisbyte=1 goto .d
  200. .c    ldx    &str+1
  201. .d    if    &deref>0 then
  202.     jsr    deref
  203. &deref    seta    &deref-1
  204.     goto    .d
  205.     endif
  206.     mexit
  207. .imm
  208. &str    setc    &substr(&str,2,999)
  209.     if    &substr(&str,1,1)='<' then
  210. axisbyte    set    1
  211. &str    setc    &substr(&str,2,999)
  212.     endif
  213.     lda    #<&str
  214.     if    axisbyte=0 then
  215.     ldx    #>&str
  216.     endif
  217.     MEND
  218.  
  219. ***************************************
  220.  
  221.     MACRO
  222.     aycorm    &op
  223. ayisbyte    set    0
  224.     lclc    &str
  225. &str    setc    &op
  226.     if    &substr(&str,1,1)='#' goto .imm
  227.     if    &substr(&str,1,1)<>'*' then
  228.     aerror    'non-variable parameter must start with a # or *'
  229.     mexit
  230.     endif
  231. &str    setc    &substr(&str,2,999)
  232.     lcla    &deref
  233. &deref    seta    0
  234. .a    if    &substr(&str,1,1)<>'*' goto .b
  235. &str    setc    &substr(&str,2,999)
  236. &deref    seta    &deref+1
  237.     goto    .a
  238. .b    if    &substr(&str,1,1)='<' then
  239. ayisbyte    set    1
  240. &str    setc    &substr(&str,2,999)
  241.     endif
  242.     lda    &str
  243.     if    &deref>0 goto .c
  244.     if    ayisbyte=1 goto .d
  245. .c    ldy    &str+1
  246. .d    if    &deref>0 then
  247.     jsr    deref
  248. &deref    seta    &deref-1
  249.     goto    .d
  250.     endif
  251.     mexit
  252. .imm
  253. &str    setc    &substr(&str,2,999)
  254.     if    &substr(&str,1,1)='<' then
  255. ayisbyte    set    1
  256. &str    setc    &substr(&str,2,999)
  257.     endif
  258.     lda    #<&str
  259.     if    ayisbyte=0 then
  260.     ldy    #>&str
  261.     endif
  262.     MEND
  263.  
  264.  
  265. ***************************************
  266.  
  267.     MACRO
  268.     fparm    &op
  269. finline    set    0
  270.     lclc    &str
  271. &str    setc    &op
  272.     if    &substr(&str,1,1)='#' goto .imm
  273.     if    &substr(&str,1,1)<>'*' then
  274.     aerror    'non-variable parameter must start with a # or *'
  275.     mexit
  276.     endif
  277.     lcla    &deref
  278. &deref    seta    -1
  279. .a    if    &substr(&str,1,1)<>'*' goto .b
  280. &str    setc    &substr(&str,2,999)
  281. &deref    seta    &deref+1
  282.     goto    .a
  283. .b    if    &deref=0 then
  284.     lda    #<&str
  285.     ldy    #>&str
  286.     mexit
  287.     endif
  288.     lda    &str
  289.     ldy    &str+1
  290. .c
  291. &deref    seta    &deref-1
  292.     if    &deref=0 goto .e
  293.     jsr    deref
  294.     goto    .c
  295. .e    mexit
  296. .imm
  297. finline    set    1
  298.     MEND
  299.  
  300.  
  301. *****************************************************************
  302. *****************************************************************
  303. *****************************************************************
  304.  
  305.  
  306.     MACRO
  307. &lab    _skipbyte
  308. &lab    dc.b    $24
  309.     MEND
  310.  
  311.  
  312. *****************************************************************
  313.  
  314.  
  315.     MACRO
  316. &lab    _skipword
  317. &lab    dc.b    $2C
  318.     MEND
  319.  
  320.  
  321. *****************************************************************
  322.  
  323.  
  324.     MACRO
  325. &lab    _int    &op
  326. &lab    aycorm    &op
  327.     if    ayisbyte=1 then
  328.     ldy    #0
  329.     endif
  330.     MEND
  331.  
  332.  
  333. *****************************************************************
  334.  
  335.  
  336.     MACRO
  337. &lab    _ptr    &op
  338. &lab    aycorm    &op
  339.     if    ayisbyte=1 then
  340.     ldy    #0
  341.     endif
  342.     MEND
  343.  
  344.  
  345. *****************************************************************
  346.  
  347.  
  348.     MACRO
  349. &lab    _byte    &op
  350. &lab    acorm    &op
  351.     MEND
  352.  
  353.  
  354. *****************************************************************
  355. *****************************************************************
  356. *****************************************************************
  357.  
  358.  
  359. * This macro initializes everything necessary in the runtime and runtime
  360. * macros.  It initializes global macro variables and resets everything
  361. * in the runtime so the application can resume if the user presses a reset.
  362.     MACRO
  363. &lab    _rtreset
  364. &lab    jsr    rtreset
  365.     MEND
  366.  
  367.  
  368. ***************************************
  369.  
  370.  
  371. * This macro is used to turn on the hi-bit for characters that are sent to rtcout.
  372.     MACRO
  373. &lab    _hibitchrs
  374. &lab    jsr    hibitchrs
  375.     MEND
  376.  
  377.  
  378. ***************************************
  379.  
  380.  
  381. * This macro is used to turn off the hi-bit for characters that are sent to rtcout.
  382.     MACRO
  383. &lab    _lowbitchrs
  384. &lab    jsr    lowbitchrs
  385.     MEND
  386.  
  387.  
  388. ***************************************
  389.  
  390.  
  391. * This macro is used to make sure that characters sent to rtcout are used as-is.  There
  392. * will be no modification of the hi-bit.
  393.     MACRO
  394. &lab    _regchrs
  395. &lab    jsr    regchrs
  396.     MEND
  397.  
  398.  
  399. ***************************************
  400.  
  401.  
  402. * This macro prints a character.  This character is either already in the acc
  403. * (no operand), or what is described by the operand.  The operand can either
  404. * be an absolute or a value in memory.
  405. * (acorm means load Acc with a Constant OR Memory value).
  406.     MACRO
  407. &lab    _rtcout    &op
  408. &lab
  409.     if    &op='' goto .jsr
  410.     acorm    &op
  411. .jsr    jsr    rtcout
  412.     MEND
  413.  
  414.  
  415. ***************************************
  416.  
  417.  
  418. * This macro prints ascii data following the _write macro.  The write routine
  419. * works by using the return address as a pointer to the ascii data.  The ascii
  420. * data is terminated with a 0 (C-string style).  When the write routine
  421. * encounters a 0, it sets the return address so the when an rts is executed,
  422. * it returns to the code following the 0 terminator.  As many parameters as
  423. * are desired can be passed to this routine.  If the ascii data is more than
  424. * 1 line, end it with a comma,backslash to indicate line continuation.
  425.     MACRO
  426. &lab    _write
  427. &lab    
  428.     if    &syslist[1]='' then
  429.     aerror    '_write:  must have at least one parameter'
  430.     mexit
  431.     endif
  432.     jsr    write
  433.     lcla    &i,&n
  434. &i    seta    1
  435. &n    seta    &nbr(&syslist)
  436. .a    dc.b    &syslist[&i]
  437. &i    seta    &i+1
  438.     if    &i<=&n goto .a
  439.     dc.b    0
  440.     MEND
  441.  
  442.  
  443. ***************************************
  444.  
  445.  
  446. * This macro prints a carriage return.
  447.     MACRO
  448. &lab    _writecr
  449. &lab    jsr    writecr
  450.     MEND
  451.  
  452.  
  453. ***************************************
  454.  
  455.  
  456. * This macro outputs op number of spaces.  If there is no op, then
  457. * the number of spaces to be output is assumed to be in the yreg.
  458.     MACRO
  459. &lab    _space    &op
  460. &lab    
  461.     if    &op='' goto .jsr
  462.     ycorm    &op
  463. .jsr    jsr    repeatsp
  464.     MEND
  465.  
  466.  
  467. ***************************************
  468.  
  469.  
  470. * This macro outputs op2 number of the character op1.  If there is no op1,
  471. * then the character is assumed to be in the acc.  If there is no op2, then
  472. * the number of times the char should be output is assumed to be in the yreg.
  473.     MACRO
  474. &lab    _repeat    &op1,&op2
  475. &lab    
  476.     if    &op1='' goto .a
  477.     acorm    &op1
  478. .a    if    &op2='' goto .jsr
  479.     ycorm    &op2
  480. .jsr    jsr    repeat
  481.     MEND
  482.  
  483.  
  484. ***************************************
  485.  
  486.  
  487. * This macro prints a c string pointed to by the operand.
  488.     MACRO
  489. &lab    _wrcstr    &op
  490. &lab
  491.     if    &op='' goto .jsr
  492.     _ptr    &op
  493. .jsr    jsr    wrcstr
  494.     MEND
  495.  
  496.  
  497. ***************************************
  498. ***************************************
  499. ***************************************
  500.  
  501.  
  502. * This macro sets signed mode.  Printing decimal numbers is affected by this.
  503.     MACRO
  504. &lab    _signed
  505. &lab    jsr    signed
  506.     MEND
  507.  
  508.  
  509. ***************************************
  510.  
  511.  
  512. * This macro sets unsigned mode.  Printing decimal numbers is affected by this.
  513.     MACRO
  514. &lab    _unsigned
  515. &lab    jsr    unsigned
  516.     MEND
  517.  
  518.  
  519. ***************************************
  520.  
  521.  
  522. * This macro does a two's compliment on the variable.
  523.     MACRO
  524. &lab    _chngsgn
  525. &lab    jsr    chngsgn
  526.     MEND
  527.  
  528.  
  529. ***************************************
  530.  
  531.  
  532. * This macro prints a 1-byte decimal value.  This value is either already in
  533. * the acc (no operand), or what is described by the operand.  The operand can
  534. * either be an absolute or a value in memory.
  535.     MACRO
  536. &lab    _decoutl    &op
  537. &lab    
  538.     if    &op='' goto .jsr
  539.     acorm    &op
  540. .jsr    jsr    decoutl
  541.     MEND
  542.  
  543.  
  544. ***************************************
  545.  
  546.  
  547. * This macro prints a 2-byte decimal value.  This value is stored in a
  548. * variable.  The variable number is either already in the xreg (no operand),
  549. * or is determined by the operand.
  550.     MACRO
  551. &lab    _vdecout    &op
  552. &lab    
  553.     if    &op='' goto .jsr
  554.     ldx    #<&op
  555. .jsr    jsr    vdecout
  556.     MEND
  557.  
  558.  
  559. ***************************************
  560.  
  561.  
  562. * This macro prints a 1- or 2-byte decimal value.  This value is either already
  563. * in the acc,y (no operand), or what is described by the operand.  The operand
  564. * can either be an absolute or a value in memory.
  565.     MACRO
  566. &lab    _decout    &op
  567. &lab    
  568.     if    &op='' goto .jsr
  569.     aycorm    &op
  570.     if    ayisbyte=1 then
  571.     jsr    decoutl
  572.     mexit
  573.     endif
  574. .jsr    jsr    decout
  575.     MEND
  576.  
  577.  
  578. ***************************************
  579.  
  580.  
  581. * This macro sets pad mode for hex.  The value is either already in the acc
  582. * (no operand), or what is described by the operand.  The operand can either
  583. * be an absolute or a value in memory.  Printing hex numbers is affected by
  584. * this.
  585.     MACRO
  586. &lab    _hexpad    &op
  587. &lab    
  588.     if    &op='' goto .jsr
  589.     acorm    &op
  590. .jsr    jsr    hexpad
  591.     MEND
  592.  
  593.  
  594. ***************************************
  595.  
  596.  
  597. * This macro sets no pad mode for hex.  Printing hex numbers is affected by
  598. * this.
  599.     MACRO
  600. &lab    _hexnopad
  601. &lab    jsr    hexnopad
  602.     MEND
  603.  
  604.  
  605. ***************************************
  606.  
  607.  
  608. * This macro prints a 1-byte hex value.  This value is either already in the
  609. * acc (no operand), or what is described by the operand.  The operand can
  610. * either be an absolute or a value in memory.
  611.     MACRO
  612. &lab    _hexoutl    &op
  613. &lab    
  614.     if    &op='' goto .jsr
  615.     acorm    &op
  616. .jsr    jsr    hexoutl
  617.     MEND
  618.  
  619.  
  620. ***************************************
  621.  
  622.  
  623. * This macro prints a 2-byte hex value.  This value is stored in a variable.
  624. * The variable number is either already in the xreg (no operand), or is
  625. * determined by the operand.
  626.     MACRO
  627. &lab    _vhexout    &op
  628. &lab    
  629.     if    &op='' goto .jsr
  630.     ldx    #<&op
  631. .jsr    jsr    vhexout
  632.     MEND
  633.  
  634.  
  635. ***************************************
  636.  
  637.  
  638. * This macro prints a 1- or 2-byte hex value.  This value is either already in
  639. * the acc,y (no operand), or what is described by the operand.  The operand can
  640. * either be an absolute or a value in memory.
  641.     MACRO
  642. &lab    _hexout    &op
  643. &lab    
  644.     if    &op='' goto .jsr
  645.     _int    &op
  646. .jsr    jsr    hexout
  647.     MEND
  648.  
  649.  
  650. ***************************************
  651.  
  652.  
  653. * This macro adds a variable to the destination variable.  If there is no
  654. * op1, then the destination variable number is assumed to be in the xreg.
  655. * If there is no op2, then the source variable number is assumed to be in
  656. * the yreg.
  657.     MACRO
  658. &lab    _addvar    &op1,&op2
  659. &lab
  660.     if    &op1='' goto .a
  661.     ldx    #<&op1
  662. .a    if    &op2='' goto .jsr
  663.     ldy    #<&op2
  664. .jsr    jsr    addvar
  665.     MEND
  666.  
  667.  
  668. ***************************************
  669.  
  670.  
  671. * This macro adds a 1-byte value to the destination variable.  If there is
  672. * no op1, then the destination variable number is assumed to be in the xreg.
  673. * If there is no op2, then the value is assumed to be in the acc.
  674.     MACRO
  675. &lab    _addl    &op1,&op2
  676. &lab
  677.     if    &op1='' goto .a
  678.     ldx    #<&op1
  679. .a    if    &op2='' goto .jsr
  680.     acorm    &op2
  681. .jsr    jsr    addconl
  682.     MEND
  683.  
  684.  
  685. ***************************************
  686.  
  687.  
  688. * This macro adds a 2-byte value to the destination variable.  If there is
  689. * no op1, then the destination variable number is assumed to be in the xreg.
  690. * If there is no op2, then the value is assumed to be in acc,y.
  691.     MACRO
  692. &lab    _add    &op1,&op2
  693. &lab
  694.     if    &op1='' goto .a
  695.     ldx    #<&op1
  696. .a    if    &op2='' goto .jsr
  697.     aycorm    &op2
  698.     if    ayisbyte=1 then
  699.     jsr    addconl
  700.     mexit
  701.     endif
  702. .jsr    jsr    addcon
  703.     MEND
  704.  
  705.  
  706. ***************************************
  707.  
  708.  
  709. * This macro subtracts a variable from the destination variable.  If there is
  710. * no op1, then the destination variable number is assumed to be in the xreg.
  711. * If there is no op2, then the source variable number is assumed to be in
  712. * the yreg.
  713.     MACRO
  714. &lab    _subvar    &op1,&op2
  715. &lab
  716.     if    &op1='' goto .a
  717.     ldx    #<&op1
  718. .a    if    &op2='' goto .jsr
  719.     ldy    #<&op2
  720. .jsr    jsr    subvar
  721.     MEND
  722.  
  723.  
  724. ***************************************
  725.  
  726.  
  727. * This macro subtracts a 1-byte value from the destination variable.  If there
  728. * is no op1, then the destination variable number is assumed to be in the xreg.
  729. * If there is no op2, then the value is assumed to be in the acc.
  730.     MACRO
  731. &lab    _subl    &op1,&op2
  732. &lab
  733.     if    &op1='' goto .a
  734.     ldx    #<&op1
  735. .a    if    &op2='' goto .jsr
  736.     acorm    &op2
  737. .jsr    jsr    subconl
  738.     MEND
  739.  
  740.  
  741. ***************************************
  742.  
  743.  
  744. * This macro subtracts a 2-byte value from the destination variable.  If there
  745. * is no op1, then the destination variable number is assumed to be in the xreg.
  746. * If there is no op2, then the value is assumed to be in acc,y.
  747.     MACRO
  748. &lab    _sub    &op1,&op2
  749. &lab
  750.     if    &op1='' goto .a
  751.     ldx    #<&op1
  752. .a    if    &op2='' goto .jsr
  753.     aycorm    &op2
  754.     if    ayisbyte=1 then
  755.     jsr    subconl
  756.     mexit
  757.     endif
  758. .jsr    jsr    subcon
  759.     MEND
  760.  
  761.  
  762. ***************************************
  763.  
  764.  
  765. * This macro multiplies the destination variable by a variable.  If there is
  766. * no op1, then the destination variable number is assumed to be in the xreg.
  767. * If there is no op2, then the source variable number is assumed to be in
  768. * the yreg.
  769.     MACRO
  770. &lab    _mulvar    &op1,&op2
  771. &lab
  772.     if    &op1='' goto .a
  773.     ldx    #<&op1
  774. .a    if    &op2='' goto .jsr
  775.     ldy    #<&op2
  776. .jsr    jsr    mulvar
  777.     MEND
  778.  
  779.  
  780. ***************************************
  781.  
  782.  
  783. * This macro multiplies the destination variable by a 1-byte value.  If there
  784. * is no op1, then the destination variable number is assumed to be in the xreg.
  785. * If there is no op2, then the value is assumed to be in the acc.
  786.     MACRO
  787. &lab    _mull    &op1,&op2
  788. &lab
  789.     if    &op1='' goto .a
  790.     ldx    #<&op1
  791. .a    if    &op2='' goto .jsr
  792.     acorm    &op2
  793. .jsr    jsr    mulconl
  794.     MEND
  795.  
  796.  
  797. ***************************************
  798.  
  799.  
  800. * This macro multiplies the destination variable by a 2-byte value.  If there
  801. * is no op1, then the destination variable number is assumed to be in the xreg.
  802. * If there is no op2, then the value is assumed to be in acc,y.
  803.     MACRO
  804. &lab    _mul    &op1,&op2
  805. &lab
  806.     if    &op1='' goto .a
  807.     ldx    #<&op1
  808. .a    if    &op2='' goto .jsr
  809.     aycorm    &op2
  810.     if    ayisbyte=1 then
  811.     jsr    mulconl
  812.     mexit
  813.     endif
  814. .jsr    jsr    mulcon
  815.     MEND
  816.  
  817.  
  818. ***************************************
  819.  
  820.  
  821. * This macro divides the destination variable by a variable.  If there is
  822. * no op1, then the destination variable number is assumed to be in the xreg.
  823. * If there is no op2, then the source variable number is assumed to be in
  824. * the yreg.  The remainder from the divide is in the acc,y.
  825.     MACRO
  826. &lab    _divvar    &op1,&op2
  827. &lab
  828.     if    &op1='' goto .a
  829.     ldx    #<&op1
  830. .a    if    &op2='' goto .jsr
  831.     ldy    #<&op2
  832. .jsr    jsr    divvar
  833.     MEND
  834.  
  835.  
  836. ***************************************
  837.  
  838.  
  839. * This macro divides the destination variable by a 1-byte value.  If there
  840. * is no op1, then the destination variable number is assumed to be in the xreg.
  841. * If there is no op2, then the value is assumed to be in the acc.  The
  842. * remainder from the divide is in the acc,y.
  843.     MACRO
  844. &lab    _divl    &op1,&op2
  845. &lab
  846.     if    &op1='' goto .a
  847.     ldx    #<&op1
  848. .a    if    &op2='' goto .jsr
  849.     acorm    &op2
  850. .jsr    jsr    divconl
  851.     MEND
  852.  
  853.  
  854. ***************************************
  855.  
  856.  
  857. * This macro divides the destination variable by a 2-byte value.  If there
  858. * is no op1, then the destination variable number is assumed to be in the xreg.
  859. * If there is no op2, then the value is assumed to be in acc,y.  The remainder
  860. * from the divide is in the acc,y.
  861.     MACRO
  862. &lab    _div    &op1,&op2
  863. &lab
  864.     if    &op1='' goto .a
  865.     ldx    #<&op1
  866. .a    if    &op2='' goto .jsr
  867.     aycorm    &op2
  868.     if    ayisbyte=1 then
  869.     jsr    divconl
  870.     mexit
  871.     endif
  872. .jsr    jsr    divcon
  873.     MEND
  874.  
  875.  
  876. ***************************************
  877.  
  878.  
  879. * This macro sets the current variable.  The current variable is defined by
  880. * a number in the xreg.  All runtime functions preserve the xreg, so multiple
  881. * operations can be done to the same variable without having to reload the xreg
  882. * with the variable number.
  883.     MACRO
  884. &lab    _var    &op
  885. &lab    ldx    #<&op
  886.     MEND
  887.  
  888.  
  889. ***************************************
  890.  
  891. * This macro uses a variable as a pointer and sets that variable to the value to where
  892. * that pointer currently points.  The macro preserves all registers.
  893. * The c equivalent would be (using longs instead if ints):
  894. *
  895. *    long    *ptrvar;
  896. *
  897. *    ptrvar = (long *)*ptrvar;
  898.     MACRO
  899. &lab    _vderef    &op
  900. &lab    
  901.     if    &op='' goto .jsr
  902.     ldx    #<&op
  903. .jsr    jsr    vderef
  904.     MEND
  905.  
  906.  
  907. ***************************************
  908.  
  909.  
  910. * This macro sets a variable to 0.  If there is no op1, then the destination
  911. * variable number is assumed to be in the xreg.
  912.     MACRO
  913. &lab    _set0    &op
  914. &lab    
  915.     if    &op='' goto .jsr
  916.     ldx    #<&op
  917. .jsr    jsr    setzero
  918.     MEND
  919.  
  920.  
  921. ***************************************
  922.  
  923.  
  924. * This macro sets a variable to another variable.  If there is no op1, then the
  925. * destination variable number is assumed to be in the xreg.  If there is no
  926. * op2, then the source variable number is assumed to be in the yreg.
  927.     MACRO
  928. &lab    _varcpy    &op1,&op2
  929. &lab    
  930.     if    &op1='' goto .a
  931.     ldx    #<&op1
  932. .a    if    &op2='' goto .jsr
  933.     ldy    #<&op2
  934. .jsr    jsr    seteq
  935.     MEND
  936.  
  937.  
  938. ***************************************
  939.  
  940.  
  941. * This macro sets a variable to a 1-byte value.  If there is no op1, then the
  942. * destination variable number is assumed to be in the xreg.  If there is no
  943. * op2, then the value is assumed to be in the acc.
  944.     MACRO
  945. &lab    _setl    &op1,&op2
  946. &lab    
  947.     if    &op1='' goto .a
  948.     ldx    #<&op1
  949. .a    if    &op2='' goto .jsr
  950.     acorm    &op2
  951. .jsr    jsr    setconl
  952.     MEND
  953.  
  954.  
  955. ***************************************
  956.  
  957.  
  958. * This macro sets a variable to a 2-byte value.  If there is no op1, then the
  959. * destination variable number is assumed to be in the xreg.  If there is no
  960. * op2, then the value is assumed to be in acc,y.
  961.     MACRO
  962. &lab    _set    &op1,&op2
  963. &lab    
  964.     if    &op1='' goto .a
  965.     ldx    #<&op1
  966. .a    if    &op2='' goto .jsr
  967.     aycorm    &op2
  968.     if    ayisbyte=1 then
  969.     jsr    setconl
  970.     mexit
  971.     endif
  972. .jsr    jsr    setcon
  973.     MEND
  974.  
  975.  
  976. ***************************************
  977.  
  978.  
  979. * This macro is used to set a bunch of variables to constant values.
  980. * There must be a non-zero even number of parameters.  The odd parameters
  981. * are the variables, and the even parameters are the constant values for
  982. * the preceeding parameter.  The setvars routine uses the return address
  983. * as a pointer to the data (just like the write routine).  It simply
  984. * sets the designated variable to the designated constant until it
  985. * encounters a 255 as a variable value.  A 255 is reserved for this
  986. * purpose.  This macro places a 255 at the end of the data list
  987. * automatically.
  988.     MACRO
  989. &lab    _setvars
  990. &lab    
  991.     if    &syslist[2]='' then
  992.     aerror    '_setvars:  must have at least two parameters'
  993.     mexit
  994.     endif
  995.     jsr    setvars
  996.     lcla    &i,&j,&n
  997. &i    seta    1
  998. &j    seta    2
  999. &n    seta    &nbr(&syslist)
  1000. .a    if    &syslist[&j]='' then
  1001.     aerror    '_setvars:  must have even number of parameters'
  1002.     mexit
  1003.     endif
  1004.     dc.b    &syslist[&i]
  1005.     if    &substr(&syslist[&j],1,1)<>'#' then
  1006.     aerror    '_setvars:  variables can only be set to constants -- missing #'
  1007.     mexit
  1008.     endif
  1009.     dc.w    &substr(&syslist[&j],2,999)
  1010. &i    seta    &i+2
  1011. &j    seta    &j+2
  1012.     if    &i<=&n goto .a
  1013.     dc.b    255
  1014.     MEND
  1015.  
  1016.  
  1017. ***************************************
  1018.  
  1019.  
  1020. * This macro swaps the two variables if the xreg variable is bigger than the
  1021. * yreg variable.  If there is no op1, then the destination variable number is
  1022. * assumed to be in the xreg.  If there is no op2, then the source variable
  1023. * number is assumed to be in the yreg.
  1024.     MACRO
  1025. &lab    _minswap    &op1,&op2    
  1026. &lab    
  1027.     if    &op1='' goto .a
  1028.     ldx    #<&op1
  1029. .a    if    &op2='' goto .jsr
  1030.     ldy    #<&op2
  1031. .jsr    jsr    xlty
  1032.     MEND
  1033.  
  1034.  
  1035. ***************************************
  1036.  
  1037.  
  1038. * This macro swaps the two variables if the xreg variable is smaller than the
  1039. * yreg variable.  If there is no op1, then the destination variable number is
  1040. * assumed to be in the xreg.  If there is no op2, then the source variable
  1041. * number is assumed to be in the yreg.
  1042.     MACRO
  1043. &lab    _maxswap    &op1,&op2    
  1044. &lab    
  1045.     if    &op1='' goto .a
  1046.     ldx    #<&op1
  1047. .a    if    &op2='' goto .jsr
  1048.     ldy    #<&op2
  1049. .jsr    jsr    xgty
  1050.     MEND
  1051.  
  1052.  
  1053. ***************************************
  1054.  
  1055.  
  1056. * This macro does a signed compare of two variables.  The equal status is true
  1057. * if the variables are equal.  If the xreg variable is greater or equal, then
  1058. * the carry is set.  If the xreg variable is smaller, then the carry is clear.
  1059. * If there is no op1, then the variable number is assumed to be in the xreg.
  1060. * If there is no op2, then the variable number is assumed to be in the yreg.
  1061.     MACRO
  1062. &lab    _vsgncmp    &op1,&op2    
  1063. &lab
  1064.     if    &op1='' goto .a
  1065.     ldx    #<&op1
  1066. .a    if    &op2='' goto .jsr
  1067.     ldy    #<&op2
  1068. .jsr    jsr    vifsgneq
  1069.     MEND
  1070.  
  1071.  
  1072. ***************************************
  1073.  
  1074.  
  1075. * This macro does an unsigned compare of two variables.  The equal status is
  1076. * true if the variables are equal.  If the xreg variable is greater or equal,
  1077. * then the carry is set.  If the xreg variable is smaller, then the carry is
  1078. * clear.  If there is no op1, then the variable number is assumed to be in the
  1079. * xreg.  If there is no op2, then the variable number is assumed to be in the
  1080. * yreg.
  1081.     MACRO
  1082. &lab    _vcmp    &op1,&op2    
  1083. &lab
  1084.     if    &op1='' goto .a
  1085.     ldx    #<&op1
  1086. .a    if    &op2='' goto .jsr
  1087.     ldy    #<&op2
  1088. .jsr    jsr    vifequal
  1089.     MEND
  1090.  
  1091.  
  1092. ***************************************
  1093.  
  1094.  
  1095. * This macro works the same as _vsgncmp, except that it compares a variable
  1096. * against a constant or value from memory at a specified location.
  1097.     MACRO
  1098. &lab    _sgncmp    &op1,&op2    
  1099. &lab
  1100.     if    &op1='' goto .a
  1101.     ldx    #<&op1
  1102. .a    if    &op2='' goto .jsr
  1103.     _int    &op2
  1104. .jsr    jsr    ifsgneq
  1105.     MEND
  1106.  
  1107.  
  1108. ***************************************
  1109.  
  1110.  
  1111. * This macro works the same as _vcmp, except that it compares a variable
  1112. * against a constant or value from memory at a specified location.
  1113.     MACRO
  1114. &lab    _cmp    &op1,&op2    
  1115. &lab
  1116.     if    &op1='' goto .a
  1117.     ldx    #<&op1
  1118. .a    if    &op2='' goto .jsr
  1119.     _int    &op2
  1120. .jsr    jsr    ifequal
  1121.     MEND
  1122.  
  1123.  
  1124. ***************************************
  1125. ***************************************
  1126. ***************************************
  1127.  
  1128.  
  1129. * This macro is used to seed the random number generator.  If there is
  1130. * no op1, then the random seed is assumed to be in the acc,y.
  1131.     MACRO
  1132. &lab    _rndseed    &op
  1133. &lab    
  1134.     if    &op='' goto .jsr
  1135.     _int    &op
  1136. .jsr    jsr    seedrandom
  1137.     MEND
  1138.  
  1139.  
  1140. ***************************************
  1141.  
  1142.  
  1143. * This macro is used to return a random number from 0 to op - 1.  If there is
  1144. * no op1, then the random number limit is assumed to be in the acc,y.
  1145.     MACRO
  1146. &lab    _random    &op
  1147. &lab    
  1148.     if    &op='' goto .jsr
  1149.     _int    &op
  1150. .jsr    jsr    calcrandom
  1151.     MEND
  1152.  
  1153.  
  1154. ***************************************
  1155. ***************************************
  1156. ***************************************
  1157.  
  1158.  
  1159. * This macro takes the value of a string and returns it in the acc,y.
  1160. * If there is no op1, then the string number is assumed to be in the xreg.
  1161.     MACRO
  1162. &lab    _strval    &op
  1163. &lab
  1164.     if    &op='' goto .jsr
  1165.     ldx    #<&op
  1166. .jsr    jsr    strval
  1167.     MEND
  1168.  
  1169.  
  1170. ***************************************
  1171.  
  1172.  
  1173. * This macro takes the value of op1 string starting at op2 character and
  1174. * returns it in the acc,y.  If there is no op1, then the string number is
  1175. * assumed to be in the xreg.  If there is no op2, then the character number
  1176. * is assumed to be in the yreg.
  1177.     MACRO
  1178. &lab    _midstrval &op1,&op2
  1179. &lab
  1180.     if    &op1='' goto .a
  1181.     ldx    #<&op1
  1182. .a    if    &op2='' goto .jsr
  1183.     ycorm    &op2
  1184. .jsr    jsr    midstrval
  1185.     MEND
  1186.  
  1187.  
  1188. ***************************************
  1189.  
  1190.  
  1191. * This macro prints the entire string.  If there is no op1, then the string
  1192. * number is assumed to be in the xreg.
  1193.     MACRO
  1194. &lab    _prstr    &op
  1195. &lab    
  1196.     if    &op='' goto .jsr
  1197.     ldx    #<&op
  1198. .jsr    jsr    prstr
  1199.     MEND
  1200.  
  1201.  
  1202. ***************************************
  1203.  
  1204.  
  1205. * This macro redirects output to the string.  If there is no op1, then
  1206. * the string number is assumed to be in the xreg.
  1207.     MACRO
  1208. &lab    _out2str    &op
  1209. &lab    
  1210.     if    &op='' goto .jsr
  1211.     ldx    #<&op
  1212. .jsr    jsr    out2str
  1213.     MEND
  1214.  
  1215.  
  1216. ***************************************
  1217.  
  1218.  
  1219. * This macro points a string to a designated memory location.  If there
  1220. * is no op1, then the string number is assumed to be in the xreg.
  1221.     MACRO
  1222. &lab    _strptr    &op1,&op2
  1223. &lab    
  1224.     if    &op1='' goto .a
  1225.     ldx    #<&op1
  1226. .a    if    &op2='' goto .jsr
  1227.     _ptr    &op2
  1228. .jsr    jsr    strptr
  1229.     MEND
  1230.  
  1231.  
  1232. ***************************************
  1233.  
  1234.  
  1235. * This macro clears the string.  If there is no op1, then
  1236. * the string number is assumed to be in the xreg.
  1237.     MACRO
  1238. &lab    _nullstr    &op
  1239. &lab    
  1240.     if    &op='' goto .jsr
  1241.     ldx    #<&op
  1242. .jsr    jsr    nullstr
  1243.     MEND
  1244.  
  1245.  
  1246. ***************************************
  1247.  
  1248.  
  1249. * This macro resets output to the setting prior to calling out2str.
  1250. * out2str can be called multiple times, and only one call to out2stroff
  1251. * is needed.  (out2str saved the output hook if it is DIFFERENT than
  1252. * what out2str sets it to.)
  1253.     MACRO
  1254. &lab    _out2stroff
  1255. &lab    jsr    out2stroff
  1256.     MEND
  1257.  
  1258.  
  1259. ***************************************
  1260.  
  1261.  
  1262. * This macro prints op1 string starting at the first character for op2
  1263. * characters.  If there is no op1, then the string number is assumed to be
  1264. * in the xreg.  If there is no op2, then the number of characters is assumed
  1265. * to be in the acc.
  1266.     MACRO
  1267. &lab    _prleftstr &op1,&op2
  1268. &lab
  1269.     if    &op1='' goto .a
  1270.     ldx    #<&op1
  1271. .a    if    &op2='' goto .jsr
  1272.     acorm    &op2
  1273. .jsr    jsr    prleftstr
  1274.     MEND
  1275.  
  1276.  
  1277. ***************************************
  1278.  
  1279.  
  1280. * This macro prints op1 string starting at the op2 character for op3
  1281. * characters.  If there is no op1, then the string number is assumed to be
  1282. * in the xreg.  If there is no op2, then the character number is assumed to
  1283. * be in the yreg.  If there is no op3, then the number of characters is
  1284. * assumed to be in the acc.
  1285.     MACRO
  1286. &lab    _prmidstr &op1,&op2,&op3
  1287. &lab
  1288.     if    &op1='' goto .a
  1289.     ldx    #<&op1
  1290. .a    if    &op2='' goto .b
  1291.     ycorm    &op2
  1292. .b    if    &op3='' goto .jsr
  1293.     acorm    &op3
  1294. .jsr    jsr    prmidstr
  1295.     MEND
  1296.  
  1297.  
  1298. ***************************************
  1299.  
  1300.  
  1301. * This macro copies op3 characters from op2 string to op1 string.  If there
  1302. * is no op1, then the destination string number is assumed to be in the xreg.
  1303. * If there is no op2, then the source string number is assumed to be in the
  1304. * yreg.  If there is no op3, then the number of characters is assumed to be
  1305. * in the acc.
  1306.     MACRO
  1307. &lab    _leftstrcpy &op1,&op2,&op3
  1308. &lab    
  1309.     if    &op1='' goto .a
  1310.     ldx    #<&op1
  1311. .a    if    &op2='' goto .b
  1312.     ldy    #<&op2
  1313. .b    if    &op3='' goto .jsr
  1314.     acorm    &op3
  1315. .jsr    jsr    leftstrcpy
  1316.     MEND
  1317.  
  1318.  
  1319. ***************************************
  1320.  
  1321.  
  1322. * This macro copies op2 string to op1 string.  If there is no op1, then the
  1323. * destination string number is assumed to be in the xreg.  If there is no op2,
  1324. * then the source string number is assumed to be in the yreg.
  1325.     MACRO
  1326. &lab    _strcpy &op1,&op2
  1327. &lab    
  1328.     if    &op1='' goto .a
  1329.     ldx    #<&op1
  1330. .a    if    &op2='' goto .jsr
  1331.     ldy    #<&op2
  1332. .jsr    jsr    strcpy
  1333.     MEND
  1334.  
  1335.  
  1336. ***************************************
  1337.  
  1338.  
  1339. * This macro copies op4 characters, starting at op3 character from op2 string
  1340. * to op1 string.  If there is no op1, then the destination string number is
  1341. * assumed to be in the xreg.  If there is no op2, then the source string number
  1342. * is assumed to be in the yreg.  If there is no op3, then the character number
  1343. * is assumed to be in the acc.  If there is no op4, then all characters to the
  1344. * end of the source string will be copied to the destination string.  The op4
  1345. * case is the only case where the assumed value is a particular value (#255),
  1346. * instead of what is in a register.  This is the case because there are only
  1347. * three registers.
  1348.     MACRO
  1349. &lab    _midstrcpy &op1,&op2,&op3,&op4
  1350. &lab
  1351.     if    &op4='' goto .b
  1352.     if    &op3<>'' goto .a
  1353.     pha
  1354. .a
  1355.     acorm    &op4
  1356.     sta    numtocopy
  1357.     if    &op3<>'' goto .b
  1358.     pla
  1359. .b    if    &op1='' goto .c
  1360.     ldx    #<&op1
  1361. .c    if    &op2='' goto .d
  1362.     ldy    #<&op2
  1363. .d    if    &op3='' goto .jsr
  1364.     acorm    &op3
  1365. .jsr    jsr    midstrcpy
  1366.     MEND
  1367.  
  1368.  
  1369. ***************************************
  1370.  
  1371.  
  1372. * This macro concatenates op3 characters of op2 string onto op1 string.  If
  1373. * there is no op1, then the destination string number is assumed to be in the
  1374. * xreg.  If there is no op2, then the source string number is assumed to be in
  1375. * the yreg.  If there is no op3, then the number of characters is assumed to
  1376. * be in the acc.
  1377.     MACRO
  1378. &lab    _leftstrcat &op1,&op2,&op3
  1379. &lab    
  1380.     if    &op1='' goto .a
  1381.     ldx    #<&op1
  1382. .a    if    &op2='' goto .b
  1383.     ldy    #<&op2
  1384. .b    if    &op3='' goto .jsr
  1385.     acorm    &op3
  1386. .jsr    jsr    leftstrcat
  1387.     MEND
  1388.  
  1389.  
  1390. ***************************************
  1391.  
  1392.  
  1393. * This macro concatenates op2 string onto op1 string.  If there is no op1,
  1394. * then the destination string number is assumed to be in the xreg.  If there
  1395. * is no op2, then the source string number is assumed to be in the yreg.
  1396.     MACRO
  1397. &lab    _strcat &op1,&op2
  1398. &lab    
  1399.     if    &op1='' goto .a
  1400.     ldx    #<&op1
  1401. .a    if    &op2='' goto .jsr
  1402.     ldy    #<&op2
  1403. .jsr    jsr    strcat
  1404.     MEND
  1405.  
  1406.  
  1407. ***************************************
  1408.  
  1409.  
  1410. * This macro concatenates op4 characters starting at op3 character from op2
  1411. * string onto op1 string.  If there is no op1, then the destination string
  1412. * number is assumed to be in the xreg.  If there is no op2, then the source
  1413. * string number is assumed to be in the yreg.  If there is no op3, then the
  1414. * character number is assumed to be in the acc.  If there is no op4, then all
  1415. * characters to the end of the source string will be concatenated to the
  1416. * destination string.  The op4 case is the only case where the assumed value
  1417. * is a particular value (#255), instead of what is in a register.  This is
  1418. * the case because there are only three registers.
  1419.     MACRO
  1420. &lab    _midstrcat &op1,&op2,&op3,&op4
  1421. &lab
  1422.     if    &op4='' goto .b
  1423.     if    &op3<>'' goto .a
  1424.     pha
  1425. .a
  1426.     acorm    &op4
  1427.     sta    numtocopy
  1428.     if    &op3<>'' goto .b
  1429.     pla
  1430. .b    if    &op1='' goto .c
  1431.     ldx    #<&op1
  1432. .c    if    &op2='' goto .d
  1433.     ldy    #<&op2
  1434. .d    if    &op3='' goto .jsr
  1435.     acorm    &op3
  1436. .jsr    jsr    midstrcat
  1437.     MEND
  1438.  
  1439.  
  1440. ***************************************
  1441.  
  1442.  
  1443. * This macro is used to take some literal string data and place it into
  1444. * a string.  It works very much like the write routine, except that it
  1445. * copies the characters into a string instead of printing them.  Operand
  1446. * 1 is the string variable, if there is one designated.  If there is not
  1447. * one designated, then the x-reg is assumed to already hold it.  There
  1448. * then must be a second parameter.  This parameter would be string data.
  1449. * There may be other parameters, which would also hold string data.
  1450. * When all data parameters are used by this macro, the macro then places
  1451. * a 0 terminator to indicate the end of the literal data.
  1452.     MACRO
  1453. &lab    _litstr
  1454. &lab    
  1455.     if    &syslist[2]='' then
  1456.     aerror    '_litstr:  must have a second parameter'
  1457.     mexit
  1458.     endif
  1459.     if    &syslist[1]='' goto .jsr
  1460.     ldx    #<&syslist[1]
  1461. .jsr    jsr    litstr
  1462.     lcla    &i,&n
  1463. &i    seta    2
  1464. &n    seta    &nbr(&syslist)
  1465. .a    dc.b    &syslist[&i]
  1466. &i    seta    &i+1
  1467.     if    &i<=&n goto .a
  1468.     dc.b    0
  1469.     MEND
  1470.  
  1471.  
  1472. ***************************************
  1473.  
  1474.  
  1475. * This macro returns the op2th character of op1 string.  If there is no op1,
  1476. * then the destination string number is assumed to be in the xreg.  If there
  1477. * is no op2, then the character number is assumed to be in the acc.
  1478.     MACRO
  1479. &lab    _strchr &op1,&op2
  1480. &lab    
  1481.     if    &op1='' goto .a
  1482.     ldx    #<&op1
  1483. .a    if    &op2='' goto .jsr
  1484.     acorm    &op2
  1485. .jsr    jsr    strchr
  1486.     MEND
  1487.  
  1488.  
  1489. ***************************************
  1490.  
  1491.  
  1492. * This macro returns the physical location of op1 string in memory.  The
  1493. * string location is returned in acc,y.If there is no op1, then the
  1494. * destination string number is assumed to be in the xreg.
  1495.     MACRO
  1496. &lab    _strloc &op1
  1497. &lab    
  1498.     if    &op1='' goto .jsr
  1499.     ldx    #<&op1
  1500. .jsr    jsr    strloc
  1501.     MEND
  1502.  
  1503.  
  1504. ***************************************
  1505.  
  1506.  
  1507.     MACRO
  1508. &lab    _cstr
  1509. &lab    
  1510.     if    &syslist[1]='' then
  1511.     aerror    '_write:  must have at least one parameter'
  1512.     mexit
  1513.     endif
  1514.     lcla    &i,&n
  1515. &i    seta    1
  1516. &n    seta    &nbr(&syslist)
  1517. .a    dc.b    &syslist[&i]
  1518. &i    seta    &i+1
  1519.     if    &i<=&n goto .a
  1520.     dc.b    0
  1521.     MEND
  1522.  
  1523.  
  1524. ***************************************
  1525. ***************************************
  1526. ***************************************
  1527.  
  1528.  
  1529. * This macro sets the read data pointer.  If there is no op, then the address
  1530. * for reading data is assumed to be in the acc,y.
  1531.     MACRO
  1532. &lab    _restore    &op
  1533. &lab
  1534.     if    &op='' goto .jsr
  1535.     _ptr    &op
  1536. .jsr    jsr    restore
  1537.     MEND
  1538.  
  1539.  
  1540. ***************************************
  1541.  
  1542.  
  1543. * This macro reads an int from the current data pointer and advances the
  1544. * pointer by two bytes.  If there is no op1, then the destination variable
  1545. * number is assumed to be in the xreg.
  1546.     MACRO
  1547. &lab    _readint    &op
  1548. &lab    
  1549.     if    &op='' goto .jsr
  1550.     ldx    #<&op
  1551. .jsr    jsr    readint
  1552.     MEND
  1553.  
  1554.  
  1555. ***************************************
  1556.  
  1557.  
  1558. * This macro reads string data into the designated string until the
  1559. * end-of-string character is encountered.  The data pointer is then set to
  1560. * point after this end-of-string character.  If there is no op1, then the
  1561. * destination string number is assumed to be in the xreg.
  1562.     MACRO
  1563. &lab    _readstr    &op
  1564. &lab    
  1565.     if    &op='' goto .jsr
  1566.     ldx    #<&op
  1567. .jsr    jsr    readstr
  1568.     MEND
  1569.  
  1570.  
  1571. ***************************************
  1572.  
  1573.  
  1574. * This macro is used to set the end-of-string character for _readstr.  If
  1575. * there is no op1, then the _readstr ending character is assumed to be in
  1576. * the acc.
  1577.     MACRO
  1578. &lab    _readend    &op
  1579. &lab    
  1580.     if    &op='' goto .jsr
  1581.     acorm    &op
  1582. .jsr    jsr    readend
  1583.     MEND
  1584.  
  1585.  
  1586. ***************************************
  1587. ***************************************
  1588. ***************************************
  1589.  
  1590.  
  1591. * This macro is used to define some memory as an array of up to
  1592. * 4 dimensions.  The first parameter is the location of the
  1593. * array, or where the location of the array is stored.  The second
  1594. * parameter is the size of the elements, (b)yte or (w)ord.  The 
  1595. * third parameter is the first dimension.  The macro and routines
  1596. * actually ignore this dimension, since it would only be used for
  1597. * range checking anyway.  The fourth through sixth parameters are
  1598. * optional.  The more parameters, the more dimensions in the array.
  1599.     MACRO
  1600. &lab    _array    &loc,&elesize,&op1,&op2,&op3,&op4
  1601.     lclc    &str
  1602. &str    setc    &elesize
  1603. &lab
  1604.     if    &loc='' goto .a
  1605.     aycorm    &loc
  1606.     if    ayisbyte=1 then
  1607.     ldy    #0
  1608.     endif
  1609. .a    jsr    arraybase
  1610.     if    &op4='' goto .b
  1611.     if    &substr(&op4,1,1)<>'#' then
  1612. .err    aerror    '_array:  dimensions must be constants --  parameter must be preceeded by a #'
  1613.     mexit
  1614.     endif
  1615. .b    if    &op3='' goto .c
  1616.     if    &substr(&op3,1,1)<>'#' goto .err
  1617. .c    if    &op2='' goto .d
  1618.     if    &substr(&op2,1,1)<>'#' goto .err
  1619. .d    if    &op1='' goto .e
  1620.     if    &substr(&op1,1,1)<>'#' goto .err
  1621. .e    if    &substr(&str,1,1)='#' goto .f
  1622.     aerror    '_array:  element size must be constant'
  1623.     mexit
  1624. .f
  1625. &str    setc    &substr(&str,2,999)
  1626.     if    &op4>'' goto .e4
  1627.     if    &op3>'' goto .e3
  1628.     if    &op2>'' goto .e2
  1629.     mexit
  1630. .e2    dc.w    &str
  1631.     dc.w    &substr(&op2,2,999)*&str
  1632.     dc.w    0
  1633.     mexit
  1634. .e3    dc.w    &str
  1635.     dc.w    &substr(&op2,2,999)*&substr(&op3,2,999)*&str
  1636.     dc.w    &substr(&op3,2,999)*&str
  1637.     dc.w    0
  1638.     mexit
  1639. .e4    dc.w    &str
  1640.     dc.w    &substr(&op2,2,999)*&substr(&op3,2,999)*&substr(&op4,2,999)*&str
  1641.     dc.w    &substr(&op3,2,999)*&substr(&op4,2,999)*&str
  1642.     dc.w    &substr(&op4,2,999)*&str
  1643.     dc.w    0
  1644.     mexit
  1645.     MEND
  1646.  
  1647.  
  1648. ***************************************
  1649.  
  1650.  
  1651. * This macro is used to index into the current array (defined by _array).
  1652. * The whole goal of the array handling is to index down to the row level.
  1653. * Once at the row level, you use the right-most subscript to index into
  1654. * that row.  This makes working on a row very fast, since all subscripts
  1655. * are not involved each time.  So, _index would be used for all subscripts
  1656. * except for the last subscript.  The parameter can either be a constant,
  1657. * (preceeded with a #) or can be a location in ram that holds the index
  1658. * (preceeded with an *).
  1659.     MACRO
  1660. &lab    _index    &op1,&op2,&op3
  1661. &lab
  1662.     if    &op1='' goto .a
  1663.     aycorm    &op1
  1664.     if    ayisbyte=1 then
  1665.     jsr    arraylindx1
  1666.     else
  1667.     jsr    arrayindx1
  1668.     endif
  1669. .a    if    &op2='' goto .b
  1670.     aycorm    &op2
  1671.     if    ayisbyte=1 then
  1672.     jsr    arraylindx2
  1673.     else
  1674.     jsr    arrayindx2
  1675.     endif
  1676. .b    if    &op3='' goto .c
  1677.     aycorm    &op3
  1678.     if    ayisbyte=1 then
  1679.     jsr    arraylindx3
  1680.     else
  1681.     jsr    arrayindx3
  1682.     endif
  1683. .c    MEND
  1684.  
  1685.  
  1686. ***************************************
  1687.  
  1688.  
  1689. * This macro works the same as _index, except that the index is stored
  1690. * in the variable indicated.
  1691.     MACRO
  1692. &lab    _vindex    &op1,&op2,&op3
  1693. &lab
  1694.     if    &op1='' goto .a
  1695.     ldy    #<&op1
  1696.     jsr    varyindx1
  1697. .a    if    &op2='' goto .b
  1698.     ldy    #<&op2
  1699.     jsr    varyindx2
  1700. .b    if    &op3='' goto .c
  1701.     ldy    #<&op3
  1702.     jsr    varyindx3
  1703. .c    MEND
  1704.  
  1705.  
  1706. ***************************************
  1707.  
  1708.  
  1709. * This macro gets an element from the working row of the current array.
  1710. * The final index parameter is used to index into this row.
  1711.     MACRO
  1712. &lab    _get    &op1,&op2
  1713. &lab
  1714.     if    &op1='' goto .a
  1715.     ldx    #<&op1
  1716. .a    if    &op2='' goto .jsr
  1717.     aycorm    &op2
  1718.     if    ayisbyte=1 then
  1719.     jsr    getelel
  1720.     mexit
  1721.     endif
  1722. .jsr    jsr    getele
  1723.     MEND
  1724.  
  1725.  
  1726. ***************************************
  1727.  
  1728.  
  1729. * This macro gets an element from the working row of the current array.
  1730. * The final index parameter is used to index into this row.
  1731.     MACRO
  1732. &lab    _getl    &op1,&op2
  1733. &lab
  1734.     if    &op1='' goto .a
  1735.     ldx    #<&op1
  1736. .a    if    &op2='' goto .jsr
  1737.     acorm    &op2
  1738. .jsr    jsr    getelel
  1739.     MEND
  1740.  
  1741.  
  1742. ***************************************
  1743.  
  1744.  
  1745. * This macro puts an element from the working row of the current array.
  1746. * The final index parameter is used to index into this row.
  1747.     MACRO
  1748. &lab    _put    &op1,&op2
  1749. &lab
  1750.     if    &op1='' goto .a
  1751.     ldx    #<&op1
  1752. .a    if    &op2='' goto .jsr
  1753.     aycorm    &op2
  1754.     if    ayisbyte=1 then
  1755.     jsr    putelel
  1756.     mexit
  1757.     endif
  1758. .jsr    jsr    putele
  1759.     MEND
  1760.  
  1761.  
  1762. ***************************************
  1763.  
  1764.  
  1765. * This macro puts an element from the working row of the current array.
  1766. * The final index parameter is used to index into this row.
  1767.     MACRO
  1768. &lab    _putl    &op1,&op2
  1769. &lab
  1770.     if    &op1='' goto .a
  1771.     ldx    #<&op1
  1772. .a    if    &op2='' goto .jsr
  1773.     acorm    &op2
  1774. .jsr    jsr    putelel
  1775.     MEND
  1776.  
  1777.  
  1778. ***************************************
  1779.  
  1780.  
  1781. * This macro gets an element from the working row of the current array.
  1782. * The final index parameter is used to index into this row.
  1783.     MACRO
  1784. &lab    _vget    &op1,&op2
  1785. &lab
  1786.     if    &op1='' goto .a
  1787.     ldx    #<&op1
  1788. .a    if    &op2='' goto .jsr
  1789.     ldy    #<&op2
  1790. .jsr    jsr    vgetele
  1791.     MEND
  1792.  
  1793.  
  1794. ***************************************
  1795.  
  1796.  
  1797. * This macro puts an element from the working row of the current array.
  1798. * The final index parameter is used to index into this row.
  1799.     MACRO
  1800. &lab    _vput    &op1,&op2
  1801. &lab
  1802.     if    &op1='' goto .a
  1803.     ldx    #<&op1
  1804. .a    if    &op2='' goto .jsr
  1805.     ldy    #<&op2
  1806. .jsr    jsr    vputele
  1807.     MEND
  1808.  
  1809.  
  1810. ***************************************
  1811.  
  1812.  
  1813. * This macro gets the next element from the current array.
  1814.     MACRO
  1815. &lab    _getnext    &op
  1816. &lab    
  1817.     if    &op='' goto .jsr
  1818.     ldx    #<&op
  1819. .jsr    jsr    getnextele
  1820.     MEND
  1821.  
  1822.  
  1823. ***************************************
  1824.  
  1825.  
  1826. * This macro puts the next element from the current array.
  1827.     MACRO
  1828. &lab    _putnext    &op
  1829. &lab    
  1830.     if    &op='' goto .jsr
  1831.     ldx    #<&op
  1832. .jsr    jsr    putnextele
  1833.     MEND
  1834.  
  1835.  
  1836. ***************************************
  1837.